﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.ObjectModel;
using System.Linq;
using AdminModule.IndexMarkServiceReference;
using AdminModule.CommonClasses;
using System.Collections.Generic;

namespace AdminModule.StructEditStratagies
{
    public class IndexMarkStructEditStrategy2 : StructEditBaseStrategy
    {
        private int IDTerm;

        public IndexMarkStructEditStrategy2(int IDTerm)
        {
            this.IDTerm = IDTerm;
        }

        public override bool Move(DTOBase obj, DTOBase fromObject, DTOBase toObject)
        {
            DTOChilds from = fromObject as DTOChilds;
            DTOChilds to = toObject as DTOChilds;

            if (obj is AdmCharacteristic && toObject is AdmSection)
            {
                AdmCharacteristic characteristic = obj as AdmCharacteristic;
                AdmSection toSection = toObject as AdmSection;

                to.Childs.Add(obj);
                from.Childs.Remove(obj);
                characteristic.Section = toSection;

                this.SetState(characteristic, StateObject.Updated);
                return true;
            }
            if (obj is AdmSection && toObject is AdmSection)
            {
                AdmSection section = obj as AdmSection;
                AdmSection toSection = toObject as AdmSection;

                to.Childs.Add(obj);
                from.Childs.Remove(obj);
                section.ParentSection = toSection;

                this.SetState(section, StateObject.Updated);
                return true;
            }
            if (obj is AdmSection && toObject is RootTreeView)
            {
                AdmSection section = obj as AdmSection;

                to.Childs.Add(obj);
                from.Childs.Remove(obj);
                section.ParentSection = null;

                this.SetState(section, StateObject.Updated);
                return true;
            }
            return false;
        }

        public override bool Delete(DTOBase obj, DTOBase fromObject)
        {
            DTOChilds from = fromObject as DTOChilds;

            if (obj is AdmSection && fromObject is RootTreeView)
            {
                from.Childs.Remove(obj);
                --from.ChildsCount;
                this.SetState(obj, StateObject.Deleted);
                return true;
            }

            if (obj is AdmSection && fromObject is AdmSection)
            {
                from.Childs.Remove(obj);
                --from.ChildsCount;
                this.SetState(obj, StateObject.Deleted);
                return true;
            }
            if (obj is AdmCharacteristic && fromObject is AdmSection)
            {
                from.Childs.Remove(obj);
                --from.ChildsCount;
                this.SetState(obj, StateObject.Deleted);
                return true;
            }
            if (obj is AdmGradation && fromObject is AdmCharacteristic)
            {
                AdmGradation gradation = obj as AdmGradation;
                AdmCharacteristic characteristic = fromObject as AdmCharacteristic;

                characteristic.Childs.Remove(gradation);
                --characteristic.ChildsCount;
                SetState(gradation, StateObject.Deleted);
                return true;
            }
            return false;
        }

        public override bool Add(DTOBase obj, DTOBase toObject)
        {
            DTOChilds to = toObject as DTOChilds;

            if (obj is AdmSection && (toObject is AdmSection || toObject is RootTreeView))
            {
                AdmSection section = obj as AdmSection;
                section.IDTerm = this.IDTerm;

                if (toObject is AdmSection)
                {
                    section.ParentSection = (toObject as AdmSection);
                }
                if (toObject is RootTreeView)
                {
                    section.ParentSection = null;
                }

                to.Childs.AddToForward(section);

                this.SetState(section, StateObject.Created);

                return true;
            }
            if (obj is AdmCharacteristic && toObject is AdmSection)
            {
                AdmCharacteristic characteristic = obj as AdmCharacteristic;
                characteristic.Section = (toObject as AdmSection);
                characteristic.IDTerm = this.IDTerm;

                to.Childs.AddToForward(characteristic);

                this.SetState(characteristic, StateObject.Created);

                return true;
            }
            if (obj is AdmGradation && toObject is AdmCharacteristic)
            {
                AdmGradation gradation = obj as AdmGradation;
                AdmCharacteristic characteristic = toObject as AdmCharacteristic;

                gradation.ParentCharacteristic = characteristic;
                characteristic.Childs.Add(gradation);
                SetState(gradation, StateObject.Created);
                return true;

            }
            if (obj is AdmResponsible && toObject is AdmCharacteristic)
            {
                AdmResponsible responsible = obj as AdmResponsible;
                AdmCharacteristic characteristic = toObject as AdmCharacteristic;

                characteristic.Responsibles.Add(responsible);
                SetState(characteristic, StateObject.Updated);
                return true;
            }
            return false;
        }

        /// <summary>
        /// Копирует только выбранный элемент. Дочерние элементы не копируются.
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="toObject"></param>
        /// <param name="toIDTerm"></param>
        /// <returns></returns>
        public override DTOBase CopyTo(DTOBase obj, DTOBase toObject, int toIDTerm)
        {
            if (obj is AdmSection && toObject is RootTreeView)
            {
                AdmSection section = obj as AdmSection;

                section.ParentSection = null;
                section.IDTerm = toIDTerm;

                return section;
            }
            if (obj is AdmSection && toObject is AdmSection)
            {
                AdmSection section = obj as AdmSection;
                AdmSection toSection = toObject as AdmSection;

                section.ParentSection = toSection;
                section.IDTerm = toIDTerm;
                section.State = StateObject.Created;

                return section;
            }
            if (obj is AdmCharacteristic && toObject is AdmSection)
            {
                AdmCharacteristic characteristic = obj as AdmCharacteristic;
                AdmSection toSection = toObject as AdmSection;

                characteristic.Section = toSection;
                characteristic.IDTerm = toIDTerm;
                characteristic.State = StateObject.Created;

                return characteristic;
            }
            return null;
        }

        public override void Replace(DTOBase new_obj, DTOBase old_obj, DTOBase parentObject)
        {
            if (new_obj is AdmCharacteristic && old_obj is AdmCharacteristic)
            {
                AdmSection section = parentObject as AdmSection;
                AdmCharacteristic new_characteristic = new_obj as AdmCharacteristic;
                AdmCharacteristic old_characteristic = old_obj as AdmCharacteristic;

                old_characteristic.CopyFrom(new_characteristic);
            }

            if (new_obj is AdmSection && old_obj is AdmSection)
            {
                AdmSection new_section = new_obj as AdmSection;
                AdmSection old_section = old_obj as AdmSection;

                old_section.CopyFrom(new_section);
            }
        }

        /// <summary>
        /// Сравнивает 2 коллекции градаций нижнего уровная и присваивает сооьветствующие состояния удаленным и созданным градациям
        /// </summary>
        /// <param name="old">Старая коллекция градаций нижнего уровня</param>
        /// <param name="_new">Новая коллекция градаций нижнего уровня</param>
        /// <returns></returns>
        private IEnumerable<AdmGradation> GetDifference(IEnumerable<AdmGradation> old, IEnumerable<AdmGradation> _new)
        {
            IEnumerable<int> old_keys = from o in old select o.IDGradationTerm;
            IEnumerable<int> new_keys = from n in _new select n.IDGradationTerm;

            IEnumerable<AdmGradation> created = from n in _new
                                                where
                                                    !old_keys.Contains(n.IDGradationTerm)
                                                select n;

            foreach (AdmGradation g in created)
            {
                g.State = StateObject.Created;
                yield return g;
            }

            IEnumerable<AdmGradation> deleted = from o in old
                                                where
                                                    !new_keys.Contains(o.IDGradationTerm)
                                                select o;
            foreach (AdmGradation g in deleted)
            {
                g.State = StateObject.Deleted;
                yield return g;
            }
        }

        /// <summary>
        /// Принимает на вход градацию верхнего уровня и возвращает градации нижнего уровня
        /// </summary>
        /// <param name="from"></param>
        /// <returns></returns>
        private IEnumerable<AdmGradation> GetBottomGradations(AdmGradation from)
        {
            foreach (AdmGradation grad in from.Childs)
            {
                if (grad.Childs.Count == 0)
                {
                    yield return grad;
                }
                else
                {
                    foreach (AdmGradation g in GetBottomGradations(grad))
                    {
                        yield return g;
                    }
                }
            }
        }
    }
}
